home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 17 / CU Amiga Magazine's Super CD-ROM 17 (1997)(EMAP Images)(GB)[!][issue 1997-12].iso / CUCD / Programming / DiceSource / src / dutil / fdtolib.c < prev    next >
C/C++ Source or Header  |  1997-09-09  |  21KB  |  1,020 lines

  1. /*
  2.  *    (c)Copyright 1992-1997 Obvious Implementations Corp.  Redistribution and
  3.  *    use is allowed under the terms of the DICE-LICENSE FILE,
  4.  *    DICE-LICENSE.TXT.
  5.  */
  6.  
  7. /*
  8.  *  FDTOLIB.C
  9.  *
  10.  *  FDTOLIB fdfile[s] [-h hdrfile] -o libname [-mr] [-mD] [-pprefix] -I incldir
  11.  *            -prof -mc -mC -auto libname -AUTO libname
  12.  *
  13.  *  Generates a normal model or registerized modem library interface given
  14.  *  any set of FD files.
  15.  *
  16.  *  -ms, -r, and -pr are ignored
  17.  */
  18.  
  19. #ifdef AMIGA
  20. #include <exec/types.h>
  21. #include <exec/nodes.h>
  22. #include <exec/lists.h>
  23. #include <clib/exec_protos.h>
  24. #include <clib/dos_protos.h>
  25. #include <clib/alib_protos.h>
  26. #include <lib/profile.h>
  27. #include <lib/version.h>
  28. #else
  29. #include <include/lib/profile.h>
  30. #include <include/lib/version.h>
  31. #endif
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36.  
  37. #ifndef AMIGA
  38. #include <suplib/all.h>
  39. #endif
  40.  
  41. #ifndef L_tmpnam
  42. #define L_tmpnam    64
  43. #endif
  44.  
  45. #define RF_SCRATCH  0x0303
  46. #define RB_BP        (8+6)
  47. #define RF_BP        (1 << RB_BP)
  48.  
  49. IDENT("fdtolib", ".5");
  50. DCOPYRIGHT;
  51.  
  52. typedef unsigned short uword;
  53. typedef struct List    List;
  54. typedef struct Node    Node;
  55.  
  56. typedef struct LVONode {
  57.     Node    lv_Node;
  58.     short   lv_Offset;
  59. } LVONode;
  60.  
  61. typedef struct RSNode {
  62.     Node    rn_Node;
  63.     short   rn_Args;        /*    -1 specifies stack  */
  64.     short   rn_Flag;        /*    equiv/fd found        */
  65.     short   rn_Regs[32];    /*    transfer registers  */
  66. } RSNode;
  67.  
  68. void    help(int);
  69. void    ScanFD(FILE *, FILE *);
  70. void    ScanRSTmp(FILE *);
  71. void    GenerateFunction(FILE *, char *, char *, int);
  72. int    AssembleFile(char *, char *);
  73. void    JoinOutput(FILE *, char *);
  74. char    *RegMaskToStr(uword, short *);
  75. uword    RegsToMask(short *, short);
  76. char    *RegToStr(short);
  77. void    RegsCall(FILE *, char *, long, RSNode *, short *);
  78. void    StackCall(FILE *, char *, long, short *, short);
  79. short    PushMask(FILE *, uword);
  80. short    PopMask(FILE *, uword);
  81. void    AddLVOList(char *, int);
  82. void    GenerateLVOList(FILE *);
  83. void    GenerateAutoOpen(FILE *, char *);
  84. void    DicePrefix(char *, char *, char *);
  85.  
  86. List    FDList;     /*  list of FD files   */
  87. List    RSList;     /*  register spec list */
  88. List    LVOList;
  89. char    DccOptsBuf[1024];
  90. char    *OutFile;
  91. char    *HdrFile;
  92. char    *FuncPrefix = "_";
  93. char    Buf[256];
  94. char    FuncName[256];
  95. char    Prefix[64];
  96. short    RegOpt;
  97. short    Verbose;
  98. short    Symbols = 1;
  99. short    SmallData = 1;
  100. short    SmallCode = 1;
  101. short    ProfOpt;
  102. short    AutoOpt;
  103. char    *DataModel = "(A4)";
  104. char    *CodeModel = "(PC)";
  105. char    *SharedLibName;
  106.  
  107. int
  108. main(int ac, char **av)
  109. {
  110.     int i;
  111.  
  112.     NewList(&FDList);
  113.     NewList(&RSList);
  114.     NewList(&LVOList);
  115.  
  116.     DicePrefix(Prefix, av[0], "");
  117.  
  118. #ifndef LATTICE
  119. #ifndef unix
  120.     expand_args(ac, av, &ac, &av);
  121. #endif
  122. #else
  123.     setbuf(stdout, NULL);
  124. #endif
  125.  
  126.     for (i = 1; i < ac; ++i) {
  127.     char *ptr = av[i];
  128.  
  129.     if (*ptr != '-') {
  130.         Node *node = malloc(sizeof(Node));
  131.         node->ln_Name = ptr;
  132.         AddTail(&FDList, node);
  133.         continue;
  134.     }
  135.     ptr += 2;
  136.     switch(ptr[-1]) {
  137.     case 'a':
  138.         AutoOpt = 1;
  139.         SharedLibName = av[++i];
  140.         break;
  141.     case 'A':
  142.         AutoOpt = 2;
  143.         SharedLibName = av[++i];
  144.         break;
  145.     case 'p':
  146.         if (strcmp(ptr, "rof") == 0)
  147.         ProfOpt = 1;
  148.         else if (strcmp(ptr, "r") == 0)     /*  ignore -pr  */
  149.         ;
  150.         else
  151.         FuncPrefix = (*ptr) ? ptr : av[++i];
  152.         break;
  153.     case 'o':
  154.         OutFile = (*ptr) ? ptr : av[++i];
  155.         break;
  156.     case 'h':
  157.         HdrFile = (*ptr) ? ptr : av[++i];
  158.         break;
  159.     case 'm':
  160.         if (*ptr == 'r' || *ptr == 'R')
  161.         RegOpt = 1;
  162.         else if (*ptr == 'd') {
  163.         SmallData = 1;
  164.         DataModel = "(A4)";
  165.         } else if (*ptr == 'D') {
  166.         SmallData = 0;
  167.         DataModel = "";
  168.         } else if (*ptr == 'c') {
  169.         SmallCode = 1;
  170.         CodeModel = "(pc)";
  171.         } else if (*ptr == 'C') {
  172.         SmallCode = 0;
  173.         CodeModel = "";
  174.         } else if (*ptr == 's') {
  175.         /*  ignore  */
  176.         }
  177.         break;
  178.     case 'r':
  179.         /* ignore -r    */
  180.         break;
  181.     case 'v':
  182.         ++Verbose;
  183.         break;
  184.     case 'I':
  185.         sprintf(DccOptsBuf + strlen(DccOptsBuf), " -I%s", (*ptr) ? ptr : av[++i]);
  186.         break;
  187.  
  188.     case 'n':
  189.         Symbols = 0;
  190.         break;
  191.  
  192.     default:
  193.         help(1);
  194.     }
  195.     }
  196.     if (OutFile == NULL || (RegOpt && HdrFile == NULL))
  197.     help(ac != 1);
  198.  
  199.     if (RegOpt == 0 && HdrFile)
  200.     puts("Warning: header file ignored (used only with -mr)");
  201.  
  202.     /*
  203.      *    step 2, ask DCC to generate a register specification file
  204.      */
  205.  
  206.     if (RegOpt) {
  207.     FILE *fi;
  208.     char rs_tmp[L_tmpnam];
  209.  
  210.     sprintf(Buf, "%sdcc -mRRX %s -a -o %s%s",
  211.         Prefix,
  212.         HdrFile,
  213.         tmpnam(rs_tmp),
  214.         DccOptsBuf
  215.     );
  216.     if(Symbols)strcat(Buf," -s -sym");
  217.     puts(Buf);
  218. #ifdef unix
  219.         system(Buf);
  220. #else
  221.     Execute(Buf, NULL, NULL);
  222. #endif
  223.  
  224.     if ((fi = fopen(rs_tmp, "r")) == NULL) {
  225.         puts("Unable to generate register specification file");
  226.         help(20);
  227.     }
  228.     ScanRSTmp(fi);
  229.     fclose(fi);
  230.     remove(rs_tmp);
  231.     }
  232.  
  233.     /*
  234.      *    step 3
  235.      */
  236.  
  237.  
  238.     {
  239.     FILE *fi;
  240.     FILE *fo = fopen(OutFile, "w");
  241.     Node *node;
  242.  
  243.     if (fo == NULL) {
  244.         printf("Error, Unable to create %s\n", OutFile);
  245.         exit(20);
  246.     }
  247.     while ((node = RemHead(&FDList)) != NULL) {
  248.         printf("generate %s", node->ln_Name);
  249.         fi = fopen(node->ln_Name, "r");
  250.         if (fi) {
  251.         puts("");
  252.         ScanFD(fi, fo);
  253.         fclose(fi);
  254.         } else {
  255.         puts(" (open failed)");
  256.         }
  257.     }
  258.     }
  259.     {
  260. #ifdef NOTDEF
  261.     RSNode *rs;
  262.  
  263.     for (rs = RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  264.         if (rs->rn_Flag == 0)
  265.         printf("Warning, no FD entry found for: %s\n", rs->rn_Node.ln_Name);
  266.     }
  267. #endif
  268.     }
  269.     return(0);
  270. }
  271.  
  272. void
  273. help(int code)
  274. {
  275.     puts(Ident);
  276.     puts(DCopyright);
  277.     puts("FDTOLIB files/wildcard [-h hdrfile] -o libname [-mr] [-mD]");
  278.     puts("  -mr :   generate registered library from header & fd file");
  279.     puts("  -mD :   large data model (else small data model)");
  280.     exit(code);
  281. }
  282.  
  283. void
  284. ScanFD(fi, fo)
  285. FILE *fi;
  286. FILE *fo;
  287. {
  288.     char *base = NULL;
  289.     long bias = -1;
  290.     short end = 0;
  291.     short public = 1;
  292.  
  293.     char *key;
  294.  
  295.     while (fgets(Buf, sizeof(Buf), fi)) {
  296.     if (Buf[0] == '\n' || Buf[0] == '*')
  297.         continue;
  298.     if (strncmp(Buf, "##", 2) != 0) {
  299.         if (bias < 0 || base == NULL) {
  300.         printf("Error, No ##base/##bias before function: %s\n", Buf);
  301.         continue;
  302.         }
  303.         if (public && AutoOpt != 2)
  304.         GenerateFunction(fo, Buf, base, bias);
  305.         bias += 6;
  306.         continue;
  307.     }
  308.     if ((key = strtok(Buf + 2, " \t\n")) == NULL) {
  309.         printf("\tError, Illegal null directive\n");
  310.         continue;
  311.     }
  312.     if (stricmp(key, "base") == 0) {
  313.         if ((key = strtok(NULL, " \t\n")) != NULL) {
  314.         if (base)
  315.             free(base);
  316.         base = strdup(key);
  317.         } else {
  318.         printf("\tError, Illegal ##base directive\n");
  319.         }
  320.         continue;
  321.     }
  322.     if (stricmp(key, "bias") == 0) {
  323.         if ((key = strtok(NULL, " \t\n")) != NULL) {
  324.         char *dummy;
  325.  
  326.         bias = strtol(key, &dummy, 0);
  327.         if (bias <= 0)
  328.             printf("\tError, Illegal ##bias: %ld\n", bias);
  329.         } else {
  330.         printf("\tError, Illegal ##bias directive\n");
  331.         }
  332.         continue;
  333.     }
  334.     if (stricmp(key, "public") == 0) {
  335.         public = 1;
  336.         continue;
  337.     }
  338.     if (stricmp(key, "private") == 0) {
  339.         public = 0;
  340.         continue;
  341.     }
  342.     if (stricmp(key, "end") == 0) {
  343.         end = 1;
  344.         break;
  345.     }
  346.     printf("\tError, Unrecognized directive: %s\n", key);
  347.     }
  348.     if (bias < 0)
  349.     puts("\tUnexpected EOF, no ##bias");
  350.     if (base == NULL)
  351.     puts("\tUnexpected EOF, no ##base");
  352.     if (end == 0)
  353.     puts("\tUnexpected EOF, no ##end directive");
  354.     if (AutoOpt != 2)
  355.     GenerateLVOList(fo);
  356.     if (AutoOpt)
  357.     GenerateAutoOpen(fo, base);
  358. }
  359.  
  360. /*
  361.  *  funcname(var,var,var)(reg,reg,reg)        (or reg/reg)
  362.  */
  363.  
  364. static short    FRegs[128];
  365.  
  366. void
  367. GenerateFunction(fo, buf, base, bias)
  368. FILE *fo;
  369. char *buf;
  370. char *base;
  371. int bias;
  372. {
  373.     char tmpFile[L_tmpnam];
  374.     char objFile[L_tmpnam+4];
  375.     char *funcName;
  376.     FILE *ft;
  377.     short argCnt;
  378.     short noArgs = 0;
  379.  
  380.     funcName = buf;
  381.     while (*funcName && *funcName != '\t' && *funcName != ' ' && *funcName != '(')
  382.     ++funcName;
  383.     if (*funcName == ' ' || *funcName == '\t') {
  384.     while (*funcName && *funcName != '(')
  385.         *funcName++ = 0;
  386.     }
  387.     if (*funcName == '(') {
  388.     *funcName++ = 0;
  389.     if (*funcName == ')')
  390.         noArgs = 1;
  391.     }
  392.     while (*funcName && *funcName != ')')   /*  skip text args  */
  393.     ++funcName;
  394.     while (*funcName && *funcName != '(')
  395.     ++funcName;
  396.     if (noArgs == 0 && *funcName == 0) {
  397.     printf("\tError in line: %s\n", buf);
  398.     return;
  399.     }
  400.  
  401.     /*
  402.      *    get register description
  403.      */
  404.  
  405.     if (*funcName)
  406.     ++funcName;
  407.     for (argCnt = 0; *funcName && *funcName != '\n' && *funcName != ')'; ++argCnt) {
  408.     switch(*funcName) {
  409.     case 'd':
  410.     case 'D':
  411.         FRegs[argCnt] = *++funcName - '0';
  412.         ++funcName;
  413.         break;
  414.     case 'a':
  415.     case 'A':
  416.         FRegs[argCnt] = *++funcName - '0' + 8;
  417.         ++funcName;
  418.         break;
  419.     default:
  420.         printf("\tError in register spec: %s\n", funcName);
  421.         return;
  422.     }
  423.     if (*funcName == ',' || *funcName == '/')
  424.         ++funcName;
  425.     }
  426.     if (noArgs == 0 && *funcName != ')') {
  427.     printf("\tError in register spec: %s\n", funcName);
  428.     return;
  429.     }
  430.  
  431.     /*
  432.      *    generate
  433.      */
  434.  
  435.     funcName = strdup(buf);
  436.     {
  437.     RSNode *rs = NULL;
  438.  
  439.     if (Verbose)
  440.         printf("    %-15s %d %d ", funcName, -bias, argCnt);
  441.  
  442.     if (RegOpt) {
  443.         for (rs = (RSNode *)RSList.lh_Head; rs->rn_Node.ln_Succ; rs = (RSNode *)rs->rn_Node.ln_Succ) {
  444.         if (strcmp(rs->rn_Node.ln_Name + 1, funcName) == 0) {
  445.             rs->rn_Flag = 1;
  446.             break;
  447.         }
  448.         }
  449.         if (rs->rn_Node.ln_Succ == NULL) {    /* (list tail)    */
  450.         if (Verbose)
  451.             puts("NO MATCH FOUND");
  452.         return;
  453.         }
  454.  
  455.         if (rs->rn_Args >= 0 && rs->rn_Args != argCnt) {
  456.         printf("Error, argCnt mismatch %s (%d/%d)\n", rs->rn_Node.ln_Name, rs->rn_Args, argCnt);
  457.         return;
  458.         }
  459.     }
  460.     if (Verbose)
  461.         fflush(stdout);
  462.  
  463.     tmpnam(tmpFile);
  464.     sprintf(objFile, "%s.o", tmpFile);
  465.  
  466.     if (RegOpt)
  467.         sprintf(FuncName, "%s", rs->rn_Node.ln_Name);
  468.     else
  469.         sprintf(FuncName, "%s%s", FuncPrefix, funcName);
  470.  
  471.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  472.         if (ProfOpt) {
  473.         fprintf(ft, "\txref\t__ProfInit\n");
  474.         fprintf(ft, "\txref\t__ProfExec\n");
  475.  
  476.         fprintf(ft, "\n\tsection autoinit1,code\n");
  477.         fprintf(ft, "\tlea\tlp0%s,A0\n", DataModel);
  478.         fprintf(ft, "\tjsr\t__ProfInit\n");
  479.         fprintf(ft, "\n\tsection libdata,data\n");
  480.         fprintf(ft, "\tds.l\t0\n");
  481.         fprintf(ft, "lp0\n");
  482.         fprintf(ft, "\tdc.l\t0\n");
  483.         fprintf(ft, "\tdc.l\t0\n");
  484.         fprintf(ft, "\tdc.l\t0\n");
  485.         fprintf(ft, "\tdc.w\t%d\n", (40 + strlen(FuncName) + (1 + 3)) & ~3);
  486.         fprintf(ft, "\tdc.w\t0\n");
  487.         fprintf(ft, "\tdc.l\t0\n");
  488.         fprintf(ft, "\tdc.l\t0\n");
  489.         fprintf(ft, "\tdc.l\t0\n");
  490.         fprintf(ft, "\tdc.l\t0\n");
  491.         fprintf(ft, "\tdc.l\tlp1\n");
  492.         fprintf(ft, "\tdc.l\tlp2\n");
  493.         fprintf(ft, "\tdc.b\t\'%s\',0\n", FuncName);
  494.  
  495.         fprintf(ft, "\tds.l\t0\n");
  496.         }
  497.         fprintf(ft, "\n\tsection ,code\n\n");
  498.         fprintf(ft, "\txref\t%s\n\n", base);
  499.  
  500.         fprintf(ft, "\txdef\t%s\n", FuncName);
  501.         fprintf(ft, "%s:\n", FuncName);
  502.  
  503.         AddLVOList(funcName, -bias);
  504.  
  505.         if (ProfOpt) {
  506.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  507.         fprintf(ft, "lp1\n");
  508.         }
  509.  
  510.         if (RegOpt == 0 || rs->rn_Args == -1) {    /*  STACK CALL */
  511.         StackCall(ft, base, bias, FRegs, argCnt);
  512.         } else {                    /*  REG CALL   */
  513.         RegsCall(ft, base, bias, rs, FRegs);
  514.         }
  515.         fputs("\tEND\n", ft);
  516.         fclose(ft);
  517.  
  518.         /*
  519.          *    assemble the temp file
  520.          */
  521.  
  522.         if (Verbose)
  523.         puts("");
  524.         if (AssembleFile(tmpFile, objFile))
  525.         JoinOutput(fo, objFile);
  526.         remove(objFile);
  527.         remove(tmpFile);
  528.     } else {
  529.         printf("\tError, Unable to create file: %s\n", tmpFile);
  530.     }
  531.     }
  532. }
  533.  
  534. void
  535. ScanRSTmp(fi)
  536. FILE *fi;
  537. {
  538.     RSNode *rs;
  539.     char *ptr;
  540.     char *symPtr;
  541.  
  542.     while (fgets(Buf, sizeof(Buf), fi)) {
  543.     if (strnicmp(Buf, "##regspec", 9) != 0)
  544.         continue;
  545.  
  546.     for (ptr = Buf + 9; *ptr == ' ' || *ptr == '\t'; ++ptr);
  547.     symPtr = ptr;
  548.     while (*ptr && *ptr != '(')
  549.         ++ptr;
  550.     if (*ptr != '(') {
  551.         printf("Error scanning RS file: %s\n", Buf);
  552.         continue;
  553.     }
  554.     *ptr++ = 0;
  555.     rs = malloc(sizeof(RSNode) + strlen(symPtr) + 1);
  556.     rs->rn_Node.ln_Name = (char *)(rs + 1);
  557.     rs->rn_Flag = 0;
  558.     strcpy(rs->rn_Node.ln_Name, symPtr);
  559.  
  560.     if (*ptr == '*') {
  561.         rs->rn_Args = -1;
  562.         while (*ptr && *ptr != ')')
  563.         ++ptr;
  564.     } else {
  565.         rs->rn_Args = 0;
  566.         while (*ptr && *ptr != ')') {
  567.         switch(*ptr) {
  568.         case 'd':
  569.         case 'D':
  570.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0';
  571.             ptr += 2;
  572.             break;
  573.         case 'a':
  574.         case 'A':
  575.             rs->rn_Regs[rs->rn_Args++] = ptr[1] - '0' + 8;
  576.             ptr += 2;
  577.             break;
  578.         default:
  579.             printf("Error, Illegal RS file register spec: %s\n", ptr);
  580.             ptr = "";
  581.             break;
  582.         }
  583.         if (*ptr == ',')
  584.             ++ptr;
  585.         }
  586.     }
  587.     if (*ptr != ')') {
  588.         printf("Error scanning RS file: %s\n", symPtr + strlen(symPtr) + 1);
  589.         continue;
  590.     }
  591.     if (Verbose > 1)
  592.         printf("RS-SCAN: %s (%d)\n", rs->rn_Node.ln_Name, rs->rn_Args);
  593.     AddTail((struct List *)&RSList, &rs->rn_Node);
  594.     }
  595. }
  596.  
  597. int
  598. AssembleFile(inFile, outFile)
  599. char *inFile;
  600. char *outFile;
  601. {
  602.     remove(outFile);
  603.  
  604.     if (Verbose > 2) {
  605.     FILE *fi;
  606.  
  607.     if ((fi = fopen(inFile, "r")) != NULL) {
  608.         while (fgets(Buf, sizeof(Buf), fi))
  609.         fputs(Buf, stdout);
  610.         fclose(fi);
  611.     }
  612.     }
  613. /*    sprintf(Buf, "%sdas %s -o %s -nu -sym", */
  614.     sprintf(Buf, "%sdas %s -o %s",
  615.     Prefix,
  616.     inFile,
  617.     outFile
  618.      );
  619.      if (Verbose > 0)
  620.      puts(Buf);
  621.      if(Symbols)strcat(Buf," -s");
  622. #ifdef unix
  623.     system(Buf);
  624. #else
  625.     Execute(Buf, NULL, NULL);
  626. #endif
  627.     return(1);
  628. }
  629.  
  630. void
  631. JoinOutput(fo, file)
  632. FILE *fo;
  633. char *file;
  634. {
  635.     FILE *fi;
  636.     short c;
  637.  
  638.     if ((fi = fopen(file, "r")) != NULL) {
  639.     while ((c = getc(fi)) != EOF)
  640.         putc(c, fo);
  641.     fclose(fi);
  642.     } else {
  643.     printf("Error, Can't read %s\n", file);
  644.     }
  645. }
  646.  
  647. /*
  648.  *  Generate assembly for a stack based call
  649.  */
  650.  
  651. void
  652. StackCall(FILE *ft, char *base, long bias, short *regs, short args)
  653. {
  654.     uword mask = (RegsToMask(regs, args) | RF_BP) & ~RF_SCRATCH;
  655.     char *ptr;
  656.     short i;
  657.     short j;
  658.     short n;
  659.  
  660.     /*
  661.      *    step 1, what regs need to be saved?
  662.      */
  663.  
  664.     n = PushMask(ft, mask);
  665.  
  666.     /*
  667.      *    step 2, load regs from stack
  668.      */
  669.  
  670.     for (i = j = 0; i < args; i = j) {
  671.     uword lmask = 1 << regs[i];
  672.     short ln;
  673.     int offset = n * 4 + i * 4 + 4;
  674.  
  675.     for (j = i + 1; j < args; ++j) {
  676.         if (regs[j] < regs[j-1])
  677.         break;
  678.         lmask |= 1 << regs[j];
  679.     }
  680.     ptr = RegMaskToStr(lmask, &ln);
  681.     if (ln > 1)
  682.         fprintf(ft, "\tmovem.l\t%d(sp),%s\n", offset, ptr);
  683.     else if (ln > 0)
  684.         fprintf(ft, "\tmove.l\t%d(sp),%s\n", offset, ptr);
  685.     }
  686.     /*
  687.      *    step 3, load library base register
  688.      */
  689.  
  690.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  691.  
  692.     /*
  693.      *    step 4, make call & return
  694.      */
  695.  
  696.     if (n) {
  697.     fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  698.     PopMask(ft, mask);
  699.     if (ProfOpt) {
  700.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  701.         fprintf(ft, "lp2\n");
  702.     }
  703.     fprintf(ft, "\tRTS\n");
  704.     } else {
  705.     if (ProfOpt) {
  706.         fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  707.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  708.         fprintf(ft, "lp2\n");
  709.         fprintf(ft, "\tRTS\n");
  710.     } else {
  711.         fprintf(ft, "\tjmp\t-%ld(A%d)\n", bias, RB_BP - 8);
  712.     }
  713.     }
  714. }
  715.  
  716. /*
  717.  *  Generate assembly for a register based call
  718.  */
  719.  
  720. void
  721. RegsCall(ft, base, bias, rs, regs)
  722. FILE *ft;
  723. char *base;
  724. long bias;
  725. RSNode *rs;
  726. short *regs;
  727. {
  728.     uword mask = (RegsToMask(regs, rs->rn_Args) | RF_BP) & ~RF_SCRATCH;
  729.     short i;
  730.     short j;
  731.     short n;
  732.  
  733.     /*
  734.      *    step 1, what regs need to be saved?
  735.      */
  736.  
  737.     n = PushMask(ft, mask);
  738.  
  739.     /*
  740.      *    step 2, load regs from other regs.  If destination is 'in use',
  741.      *    then use EXG instead (and track where the reg went to)
  742.      *
  743.      *    src:    rs->rn_Regs[i]
  744.      *    dest:    regs[i]
  745.      */
  746.  
  747.     for (i = 0; i < rs->rn_Args; ++i) {
  748.     for (j = 0; j < rs->rn_Args; ++j) { /*    is dest in use? */
  749.         if (i != j && regs[i] == rs->rn_Regs[j])
  750.         break;
  751.     }
  752.     if (j == rs->rn_Args) {         /*  not in use        */
  753.         if (regs[i] != rs->rn_Regs[i]) {    /*  not in right plac    */
  754.         fprintf(ft, "\tmove.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  755.         rs->rn_Regs[i] = -1;
  756.         }
  757.     } else {
  758.         fprintf(ft, "\texg.l\t%s,%s\n", RegToStr(rs->rn_Regs[i]), RegToStr(regs[i]));
  759.         rs->rn_Regs[j] = rs->rn_Regs[i];
  760.         rs->rn_Regs[i] = -1;
  761.     }
  762.     }
  763.  
  764.     /*
  765.      *    step 3, load library base register
  766.      */
  767.  
  768.     fprintf(ft, "\tmove.l\t%s%s,A%d\n", base, DataModel, RB_BP - 8);
  769.  
  770.     /*
  771.      *    step 4, make call and return
  772.      */
  773.  
  774.     if (n) {
  775.     fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  776.     PopMask(ft, mask);
  777.  
  778.     if (ProfOpt) {
  779.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  780.         fprintf(ft, "lp2\n");
  781.     }
  782.     fprintf(ft, "\tRTS\n");
  783.     } else {
  784.     if (ProfOpt) {
  785.         fprintf(ft, "\tjsr\t-%ld(A%d)\n", bias, RB_BP - 8);
  786.         fprintf(ft, "\tjsr\t__ProfExec%s\n", CodeModel);
  787.         fprintf(ft, "lp2\n");
  788.         fprintf(ft, "\tRTS\n");
  789.     } else {
  790.         fprintf(ft, "\tjmp\t-%ld(A%d)\n", bias, RB_BP - 8);
  791.     }
  792.     }
  793. }
  794.  
  795. char *
  796. RegMaskToStr(uword mask, short *nr)
  797. {
  798.     static char buf[64];
  799.     char *ptr = buf;
  800.     short i;
  801.     short l = -1;
  802.  
  803.     *nr = 0;
  804.  
  805.     for (i = 0; i < 8; ++i) {
  806.     if (mask & (1 << i)) {
  807.         ++*nr;
  808.         if (l >= 0)
  809.         *ptr++ = '/';
  810.         ptr += sprintf(ptr, "D%d", i);
  811.         l = i;
  812.     }
  813.     }
  814.     for (i = 8; i < 16; ++i) {
  815.     if (mask & (1 << i)) {
  816.         ++*nr;
  817.         if (l >= 0)
  818.         *ptr++ = '/';
  819.         ptr += sprintf(ptr, "A%d", i - 8);
  820.         l = i;
  821.     }
  822.     }
  823.     *ptr = 0;
  824.     return(buf);
  825. }
  826.  
  827. uword
  828. RegsToMask(short *regs, short args)
  829. {
  830.     uword mask = 0;
  831.  
  832.     while (args > 0) {
  833.     mask |= 1 << *regs++;
  834.     --args;
  835.     }
  836.     return(mask);
  837. }
  838.  
  839. char *
  840. RegToStr(short rno)
  841. {
  842.     static char Buf[2][16];
  843.     static short BNo;
  844.     char *ptr = Buf[BNo];
  845.  
  846.     BNo = 1 - BNo;
  847.     if (rno < 8)
  848.     sprintf(ptr, "D%d", rno);
  849.     else
  850.     sprintf(ptr, "A%d", rno - 8);
  851.     return(ptr);
  852. }
  853.  
  854. short
  855. PushMask(FILE *fo, uword mask)
  856. {
  857.     short n;
  858.     char *ptr;
  859.  
  860.     ptr = RegMaskToStr(mask, &n);
  861.     if (n > 1)
  862.     fprintf(fo, "\tmovem.l\t%s,-(sp)\n", ptr);
  863.     else if (n > 0)
  864.     fprintf(fo, "\tmove.l\t%s,-(sp)\n", ptr);
  865.     return(n);
  866. }
  867.  
  868. short
  869. PopMask(FILE *fo, uword mask)
  870. {
  871.     short n;
  872.     char *ptr;
  873.  
  874.     ptr = RegMaskToStr(mask, &n);
  875.     if (n > 1)
  876.     fprintf(fo, "\tmovem.l\t(sp)+,%s\n", ptr);
  877.     else if (n > 0)
  878.     fprintf(fo, "\tmove.l\t(sp)+,%s\n", ptr);
  879.     return(n);
  880. }
  881.  
  882. void
  883. AddLVOList(funcName, bias)
  884. char *funcName;
  885. int bias;
  886. {
  887.     LVONode *node;
  888.  
  889.     if ((node = malloc(sizeof(LVONode) + strlen(funcName) + 1)) != NULL) {
  890.     AddTail(&LVOList, &node->lv_Node);
  891.     node->lv_Node.ln_Name = (char *)(node + 1);
  892.     strcpy(node->lv_Node.ln_Name, funcName);
  893.     node->lv_Offset = bias;
  894.     }
  895. }
  896.  
  897. void
  898. GenerateLVOList(fo)
  899. FILE *fo;
  900. {
  901.     char tmpFile[L_tmpnam];
  902.     char objFile[L_tmpnam + 4];
  903.     LVONode *node;
  904.     FILE *ft;
  905.  
  906.     tmpnam(tmpFile);
  907.     sprintf(objFile, "%s.o", tmpFile);
  908.  
  909.     if ((node = (LVONode *)RemHead((struct List *)&LVOList)) != NULL) {
  910.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  911.         fprintf(ft, "\n\tsection ,code\n\n");
  912.  
  913.         while (node) {
  914.         if (Verbose)
  915.             printf("_LVO%-20s = %d\n", node->lv_Node.ln_Name, node->lv_Offset);
  916.         fprintf(ft, "_LVO%s\tEQU\t%d\n", node->lv_Node.ln_Name, node->lv_Offset);
  917.         fprintf(ft, "\txdef\t_LVO%s\n", node->lv_Node.ln_Name);
  918.         free(node);
  919.         node = (LVONode *)RemHead((struct List *)&LVOList);
  920.         }
  921.         fputs("\tEND\n", ft);
  922.         fclose(ft);
  923.  
  924.         if (AssembleFile(tmpFile, objFile))
  925.         JoinOutput(fo, objFile);
  926.         remove(objFile);
  927.         remove(tmpFile);
  928.     }
  929.     }
  930. }
  931.  
  932. /*
  933.  *  generate auto-open tag code for this library
  934.  */
  935.  
  936. void
  937. GenerateAutoOpen(fo, base)
  938. FILE *fo;
  939. char *base;
  940. {
  941.     char tmpFile[L_tmpnam];
  942.     char objFile[L_tmpnam + 4];
  943.     FILE *ft;
  944.  
  945.     tmpnam(tmpFile);
  946.     sprintf(objFile, "%s.o", tmpFile);
  947.  
  948.     if ((ft = fopen(tmpFile, "w")) != NULL) {
  949.     fprintf(ft, "\n\txdef\t%s\n", base);
  950.     fprintf(ft, "\n\txref\t__AutoFail0\n\n");
  951.     fprintf(ft, "_LVOOpenLibrary\tequ\t-552\n");
  952.     fprintf(ft, "_LVOCloseLibrary\tequ\t-414\n\n");
  953.  
  954.     fprintf(ft, "\n\tsection autoinit0,code\n\n");
  955.  
  956.     fprintf(ft, "\tmoveq.l\t#0,D0\n");
  957.     fprintf(ft, "\tlea\tlibname(pc),A1\n");
  958.     fprintf(ft, "\tjsr\t_LVOOpenLibrary(A6)\n");
  959.     fprintf(ft, "\tmove.l\tD0,%s%s\n", base, DataModel);
  960.     fprintf(ft, "\tbeq\t__AutoFail0\n");
  961.     fprintf(ft, "\tbra\topennext\n");
  962.     fprintf(ft, "libname\tdc.b\t'%s',0\n", SharedLibName);
  963.     fprintf(ft, "\tds.w\t0\n");
  964.     fprintf(ft, "opennext\n\n");
  965.  
  966.     fprintf(ft, "\tsection autoexit0,code\n\n");
  967.     fprintf(ft, "\tmove.l\t%s%s,D0\n", base, DataModel);
  968.     fprintf(ft, "\tbeq\tclosenext\n");
  969.     fprintf(ft, "\tmove.l\tD0,A1\n");
  970.     fprintf(ft, "\tjsr\t_LVOCloseLibrary(A6)\n");
  971.     fprintf(ft, "closenext\n\n");
  972.  
  973.     fprintf(ft, "\tsection libdata,data\n\n");
  974.     fprintf(ft, "%s\tdc.l\t0\n", base);
  975.  
  976.     fputs("\tEND\n", ft);
  977.     fclose(ft);
  978.  
  979.     if (AssembleFile(tmpFile, objFile))
  980.         JoinOutput(fo, objFile);
  981.     remove(objFile);
  982.     remove(tmpFile);
  983.     }
  984. }
  985.  
  986.  
  987. #ifdef LATTICE
  988.  
  989. char *
  990. tmpnam(buf)
  991. char *buf;
  992. {
  993.     static char Buf[L_tmpnam];
  994.     static short Seq;
  995.  
  996.     if (buf == NULL)
  997.     buf = Buf;
  998.     sprintf(buf, "T:%06lx%d", (long)FindTask(NULL) >> 4, Seq++);
  999.     return(buf);
  1000. }
  1001.  
  1002. #endif
  1003.  
  1004. void
  1005. DicePrefix(char *buf, char *av0, char *app)
  1006. {
  1007.     char *ptr;
  1008.     short n = 0;
  1009.  
  1010.     for (ptr=av0+strlen(av0); ptr >= av0 && *ptr != '/' && *ptr != ':'; --ptr)
  1011.     ;
  1012.     ++ptr;
  1013.     if ((av0 = strchr(ptr, '_')) != NULL) {
  1014.     n = av0 - ptr + 1;
  1015.     strncpy(buf, ptr, n);
  1016.     }
  1017.     strcpy(buf + n, app);
  1018. }
  1019.  
  1020.